#! /usr/bin/env python
"""
::BOH
$Id: collector.py,v 1.7 2006/05/04 01:00:00

Copyright (c) 2006 George Bobeck. All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
::EOH

Data collector OWTF datagrams
"""
import sys
import os
import pickle
import MySQLdb
from time import *
from datetime import *
from reading import *
from socket import *

def conf(location):
    f = open(location,'r')
    a = f.readlines()
    fl = []
    var_list = []
    for e in a:
        if "#" not in e:
            e = e.strip('\n')
            e = e.strip('\r')
            if e == '':
                pass
            else:
                e = e.split("\t")
                try:
                    e.remove('')
                except:
                    pass
            var_list.extend(e)
    return var_list
confs = conf(sys.argv[ 1 ])

verbose = bool(confs[confs.index("verbose")+1])
host = ""
port = int(confs[confs.index("port")+1])
buf = 1024
addr = (host,port)


dbhost = confs[confs.index("dbhost")+1]
dbport = int(confs[confs.index("dbport")+1])
dbuser = confs[confs.index("dbuser")+1]
dbpasswd = confs[confs.index("dbpasswd")+1]
dbase = confs[confs.index("dbase")+1]
if verbose:
    print "Collector Settings"
    print "Localhost:",port
    print "Database Settings"
    print "Host: ",dbhost
    print "Port: ",dbport
    print "User: ",dbuser
    print "(Password Not Printed)"
    print "Database: ",dbase

# Create socket and bind to address
UDPSock = socket(AF_INET,SOCK_DGRAM)
UDPSock.bind(addr)

def dbconnect():
    global ms
    ms = MySQLdb.connect(host = dbhost,port = dbport ,user = dbuser,passwd=dbpasswd,db=dbase)
    global cur
    cur = ms.cursor()

# Receive messages
def main():
    try:
        dbconnect()
        global cur
    except:
        print "Unable to Connect to Database"
        sys.exit(1)
    while 1:
        data,addr = UDPSock.recvfrom(buf)
        if not data:
            if verbose:
                print "OOPS: Datagram Error!!"
            break
        else:
            dout = reading()
            dout = pickle.loads(data)
            try:
                
                cur.execute("""insert into monitors values (%s,%s) on duplicate key update cron = %s""",(dout.GetMID(),dout.GetTime(),dout.GetTime(),)) 
                cur.execute("""insert into sensors values (%s,%s,%s,%s,'Y') on duplicate key update active = 'Y', cron = %s""",(dout.GetMID(),dout.GetSID(),dout.GetLocation(),dout.GetTime(),dout.GetTime(),))
                cur.execute("""insert into sensor_data (sid,cron,temp,humid,v1,v2) values (%s,%s,%s,%s,%s,%s);""",(dout.GetSID(),dout.GetTime(),dout.GetTemp(),dout.GetHumid(),dout.GetV1(),dout.GetV2(),))
            except:
                # Assume DB connection broken.  Re-establish.
                try:
                    # try closing, then reconnect.
                    ms.close()
                    dbconnect()
                except:
                    # reconnect
                    dbconnect()
                # execute code again!
                cur.execute("""insert into monitors values (%s,%s) on duplicate key update cron = %s""",(dout.GetMID(),dout.GetTime(),dout.GetTime(),)) 
                cur.execute("""insert into sensors values (%s,%s,%s,'Y') on duplicate key update active = 'Y'""",(dout.GetMID(),dout.GetSID(),dout.GetLocation(),))
                cur.execute("""insert into sensor_data (sid,cron,temp,humid,v1,v2) values (%s,%s,%s,%s,%s,%s);""",(dout.GetSID(),dout.GetTime(),dout.GetTemp(),dout.GetHumid(),dout.GetV1(),dout.GetV2(),))

    # Close socket, db
    UDPSock.close()
    ms.close()
    sys.exit( 1 )

if __name__ == "__main__":
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit first parent
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "ERROR: fork #1 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1)
    # decouple from parent environment
    os.chdir("/") 
    os.setsid() 
    os.umask(0) 
    # do second fork
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit from second parent, print eventual PID before
            if verbose:
                print "Monitor PID %d" % pid 
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "ERROR: fork #2 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1) 
    main()
